package com.xzakota.minesweeper;

import com.xzakota.minesweeper.util.ResourceUtil;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * 游戏资源处理
 *
 * @author Xzakota
 */
public class R {
    private final static String SCAN_DIR_ICON = "icon/";
    private final static String SCAN_DIR_IMAGE = "image/";
    private final static String SCAN_DIR_SOUND = "sound/";
    private final static String SCAN_DIR_HTML = "html/";

    public final List<ImageIcon> ICON_LIST = new ArrayList<>();
    public final List<BufferedImage> IMAGE_LIST = new ArrayList<>();
    public final List<Clip> SOUND_LIST = new ArrayList<>();
    public final List<URL> HTML_LIST = new ArrayList<>();

    private final String theme;

    public R(String theme) {
        this.theme = theme;
        loadResource();
    }

    public ImageIcon getIconResource(int id) {
        return ICON_LIST.get(id);
    }

    public BufferedImage getImageResource(int id) {
        return IMAGE_LIST.get(id);
    }

    public Clip getSoundResource(int id) {
        return SOUND_LIST.get(id);
    }

    public URL getHTMLResource(int id) {
        return HTML_LIST.get(id);
    }

    private void loadResource() {
        try {
            loadIconResource("number.png", Icon._NUM_INDEX_S, 0, 8);
            loadIconResource("grid.png", Icon._GRID_INDEX_S, 1, 25);
            loadIconResource("mark.png", Icon._MARK_INDEX_S, 1, 6);
            loadIconResource("control.png", Icon._CONTROL_INDEX_S, 0, 2);
            loadIconResource("time.png", Icon._TIME_INDEX_S, 0, 12);

            loadImageResource("mine.png", Image.APP_ICON);
            loadImageResource("splash.png", Image.SPLASH_BG);
            loadImageResource("user.png", Image.USER_AVATAR);
            loadImageResource("logo.png", Image.APP_LOGO);

            loadSoundResource("game_start.wav", R.Sound.GAME_START);
            loadSoundResource("game_lose.wav", R.Sound.GAME_LOSE);
            loadSoundResource("game_win.wav", R.Sound.GAME_WIN);
            loadSoundResource("time_tick.wav", R.Sound.TIME_TICK);

            loadHTMLResource("help.html", R.HTML.HTML_HELP);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void loadIconResource(String fileName, int beginIndex, int direction, int... tiles) throws Exception {
        if (tiles == null || tiles.length == 0) {
            return;
        }
        BufferedImage image = ImageIO.read(ResourceUtil.getResource(theme + "/" + SCAN_DIR_ICON + fileName));

        int tw = image.getWidth();
        int th = image.getHeight();

        if (direction == 0 && tiles.length == 1) {
            th /= tiles[0];
            for (int i = 0; i < tiles[0]; i++) {
                ImageIcon icon = new ImageIcon(image.getSubimage(0, i * th, tw, th));
                ICON_LIST.add(beginIndex + i, icon);
            }
        } else if (direction == 1 && tiles.length == 1) {
            tw /= tiles[0];
            for (int i = 0; i < tiles[0]; i++) {
                ImageIcon icon = new ImageIcon(image.getSubimage(i * tw, 0, tw, th));
                ICON_LIST.add(beginIndex + i, icon);
            }
        } else if (direction == 2 && tiles.length == 2) {
            tw /= tiles[1];
            th /= tiles[0];
            for (int i = 0; i < tiles[0]; i++) {
                for (int j = 0; j < tiles[1]; j++) {
                    ImageIcon icon = new ImageIcon(image.getSubimage(j * tw, i * th, tw, th));
                    ICON_LIST.add(icon);
                }
            }
        }
    }

    private void loadImageResource(String fileName, int beginIndex) throws Exception {
        BufferedImage image = ImageIO.read(ResourceUtil.getResource(theme + "/" + SCAN_DIR_IMAGE + fileName));
        IMAGE_LIST.add(beginIndex, image);
    }

    private void loadSoundResource(String fileName, int beginIndex) {
        try {
            URL url = ResourceUtil.getResource(theme + "/" + SCAN_DIR_SOUND + fileName);
            if (url != null) {
                AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
                Clip clip = (Clip) AudioSystem.getLine(new DataLine.Info(Clip.class, audioInputStream.getFormat()));
                clip.open(audioInputStream);
                SOUND_LIST.add(beginIndex, clip);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void loadHTMLResource(String fileName, int beginIndex){
        URL url = ResourceUtil.getResource(theme + "/" + SCAN_DIR_HTML + fileName);
        if (url != null) {
            HTML_LIST.add(beginIndex, url);
        }
    }

    public static class Icon {
        private static int index = 0;
        public static final int _NUM_INDEX_S = index;
        public static final int MINE_1 = index++;
        public static final int MINE_2 = index++;
        public static final int MINE_3 = index++;
        public static final int MINE_4 = index++;
        public static final int MINE_5 = index++;
        public static final int MINE_6 = index++;
        public static final int MINE_7 = index++;
        public static final int MINE_8 = index++;
        public static final int _NUM_INDEX_E = MINE_8;

        public static final int _GRID_INDEX_S = index;
        public static final int _GRID_INDEX_E = (index += 24);

        public static final int _MARK_INDEX_S = ++index;
        public static final int MARK_SAFE = index++;
        public static final int MARK_UNSAFE = index++;
        public static final int MARK_MAYBE = index++;
        public static final int _MARK_INDEX_E = MARK_MAYBE;
        public static final int _CONTROL_INDEX_E = MARK_MAYBE;
        public static final int MARK_MINE = index++;
        public static final int MARK_MINE_EXPLODE = index++;
        public static final int MARK_WRONG_MARK = index++;
        public static final int _CONTROL_INDEX_S = index;
        public static final int CONTROL_MINE_COUNT = index++;
        public static final int CONTROL_TIME = index++;
        public static final int _TIME_INDEX_S = index;
        public static final int NUM_SPLIT = index++;
        public static final int NUM_NULL = index++;
        public static final int NUM_9 = index++;
        public static final int NUM_8 = index++;
        public static final int NUM_7 = index++;
        public static final int NUM_6 = index++;
        public static final int NUM_5 = index++;
        public static final int NUM_4 = index++;
        public static final int NUM_3 = index++;
        public static final int NUM_2 = index++;
        public static final int NUM_1 = index++;
        public static final int NUM_0 = index++;
        public static final int _TIME_INDEX_E = NUM_0;
    }

    public static class Image {
        private static int index = 0;
        public static final int APP_ICON = index++;
        public static final int SPLASH_BG = index++;
        public static final int USER_AVATAR = index++;
        public static final int APP_LOGO = index++;
    }

    public static class Sound {
        private static int index = 0;
        public static final int GAME_START = index++;
        public static final int GAME_LOSE = index++;
        public static final int GAME_WIN = index++;
        public static final int TIME_TICK = index++;
    }

    public static class HTML {
        private static int index = 0;
        public static final int HTML_HELP = index++;
    }
}
